﻿using System;
using System.ComponentModel;
using System.Data.Services.Client;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using BuildARoute.BARDataService;

namespace BuildARoute.Views
{
    public partial class UserTools : Page, INotifyPropertyChanged
    {

        #region ctor
        public UserTools()
        {
            InitializeComponent();
            Loaded += new RoutedEventHandler(UserTools_Loaded);
        }


        #endregion

        #region method, events and handlers
        void UserTools_Loaded(object sender, RoutedEventArgs arg)
        {
            WebContext.Current.Authentication.LoggedIn += (s, e) => UpdateVisibilitiesForAuthenticationStatus();
            WebContext.Current.Authentication.LoggedOut += (s, e) => UpdateVisibilitiesForAuthenticationStatus();

            datacontext = new TourGuideSolutionDataEntities(new Uri(App.Current.SvcPath));
            datacontext.MergeOption = MergeOption.PreserveChanges;

            tourCollection = new DataServiceCollection<Tour>();
            tourCollectionViewSource = this.Resources["tourCollectionViewSource"] as CollectionViewSource;

            tourCollection.LoadCompleted += new EventHandler<LoadCompletedEventArgs>(tourCollection_LoadCompleted);

            UpdateVisibilitiesForAuthenticationStatus();
        }

        void tourCollection_LoadCompleted(object sender, LoadCompletedEventArgs e)
        {
            if (e.Error == null)
            {
                //Load all pages before binding
                if (tourCollection.Continuation != null)
                {
                    tourCollection.LoadNextPartialSetAsync();
                }
                else
                {
                    //Bind
                    tourCollectionViewSource.Source = tourCollection;
                    
                }
            }
            else
            {
                MessageBox.Show(string.Format("Error: {0} while loading tours.", e.Error.Message));
            }
        }

        private void addButton_Click(object sender, RoutedEventArgs e)
        {
            var newTour = new Tour();
            newTour.Title = "";
            newTour.TourID = Guid.NewGuid();
            newTour.DateCreated = DateTime.Now;
            newTour.LastEdit = DateTime.Now;
            newTour.Provider = (string)WebContext.Current.User.GetIdentity();

            datacontext.AddToTours(newTour);
            
            var addTourWindow = new CreateTourWindow() { CurrentTour = newTour, Context = datacontext, IsNew = true };
            addTourWindow.Closed += new EventHandler(addTourWindow_Closed);

            addTourWindow.Show();
        }

        void addTourWindow_Closed(object sender, EventArgs e)
        {
            //TODO implement cancel changes if no Save button was pressed in the sender CreateTourWindow
            trySaveChanges();

            UpdateVisibilitiesForAuthenticationStatus();

        }

        private void deleteButton_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            if (tourListBox.SelectedIndex < 0)
            {
                MessageBox.Show("Please, SELECT FIRST the route you want to delete.");
                return;
            }
            else
            {
                var deleteme = tourListBox.SelectedItem as Tour;

                tourCollection.Remove(deleteme);
                trySaveChanges();


            }
        }

        private void editButton_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            if (tourListBox.SelectedIndex < 0)
            {
                MessageBox.Show("Please, SELECT FIRST the route you want to edit.");
                return;
            }
            else
            {
                var currTour = (Tour)tourListBox.SelectedItem;
                var addTourWindow = new CreateTourWindow() { CurrentTour = currTour, Context = datacontext, IsNew = false };
                addTourWindow.Closed += new EventHandler(addTourWindow_Closed);
                addTourWindow.Show();
            }
        }

        private void UpdateVisibilitiesForAuthenticationStatus()
        {
            bool isLoggedIn = WebContext.Current.User.IsAuthenticated;

            ToolsVisibility = isLoggedIn ? Visibility.Visible : Visibility.Collapsed;
            UnauthenticatedVisibility = isLoggedIn ? Visibility.Collapsed : Visibility.Visible;

            if (isLoggedIn)
            {
                var query = (from tour in datacontext.Tours
                             where tour.Provider == (string)WebContext.Current.User.GetIdentity()
                             select tour).OrderByDescending(t => t.LastEdit);

                tourCollection.LoadAsync(query);
            }

        }

        void trySaveChanges()
        {
            //Try Save changes
            //try
            //{
            datacontext.BeginSaveChanges(SaveChangesOptions.Batch, OnChangesSaved, datacontext);
            //}
            //catch (Exception ex)
            //{
            //    MessageBox.Show(string.Format("The changes could not be saved to the data service.\n"
            //        + "The following error occurred: {0}", ex.Message));
            //}
        }
        private void OnChangesSaved(IAsyncResult result)
        {
            bool errorOccured = false;

            // Use the Dispatcher to ensure that the 
            // asynchronous call returns in the correct thread.
            Dispatcher.BeginInvoke(() =>
            {
                datacontext = result.AsyncState as TourGuideSolutionDataEntities;

                //try
                //{
                // Complete the save changes operation and display the response.
                DataServiceResponse response = datacontext.EndSaveChanges(result);

                foreach (ChangeOperationResponse changeResponse in response)
                {
                    if (changeResponse.Error != null) errorOccured = true;
                }
                if (!errorOccured)
                {

                    //MessageBox.Show("The changes have been saved to the data service.");
                }
                else
                {
                    MessageBox.Show("An error occured. One or more changes could not be saved.");
                }
                //}
                //catch (Exception ex)
                //{
                //    // Display the error from the response.
                //    MessageBox.Show(string.Format("The following error occured: {0}", ex.Message));
                //}
            }
            );
        }

        #endregion

        #region props and fields
        private TourGuideSolutionDataEntities datacontext;
        private DataServiceCollection<Tour> tourCollection;
        private CollectionViewSource tourCollectionViewSource;
        

        public bool IsDesignTime
        {
            get { return DesignerProperties.IsInDesignTool; }
        }

        private Visibility _toolsVisibility;
        public Visibility ToolsVisibility
        {
            get
            {
                return _toolsVisibility;
            }
            set
            {
                if (_toolsVisibility == value) return;
                _toolsVisibility = value;
                RaisePropertyChanged("ToolsVisibility");
            }
        }

        private Visibility _unauthenticatedVisibility;
        public Visibility UnauthenticatedVisibility
        {
            get
            {
                return _unauthenticatedVisibility;
            }
            set
            {
                if (_unauthenticatedVisibility == value) return;

                _unauthenticatedVisibility = value;
                RaisePropertyChanged("UnauthenticatedVisibility");

            }
        }
        #endregion

        #region INotifyPropertyChanged Members
        public event PropertyChangedEventHandler PropertyChanged;
        protected void RaisePropertyChanged(string propName)
        {
            var propChanged = PropertyChanged;
            if (propChanged != null)
            {
                propChanged(this, new PropertyChangedEventArgs(propName));
            }
        }
        #endregion

    }
}
